package com.jwt.token.interceptor;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义拦截器
 * TokenInterceptor实现了HandlerInterceptor接口，重写了preHandle方法，该方法是在每个请求之前触发执行，
 * 从request的头里面取出token，这里我们统一了存放token的键为admin-token，验证通过，放行，验证不通过，返回认证失败信息。
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${jwt.key}")
    private String jwtKey;		// 从配置中读取到 jwt 的key

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 允许跨域
        response.setHeader("Access-Control-Allow-Origin", "*");
        if (request.getMethod().equals("OPTIONS")) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        response.setCharacterEncoding("UTF-8");
        String token = request.getHeader("token");
        if (null != token) {
//            boolean verify = TokenUtil.verify(token);
            Algorithm algorithm = Algorithm.HMAC256(jwtKey);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            String jwtId = jwt.getId();
            // TODO: 优化验证token是否过期
            String tokenUser = stringRedisTemplate.opsForValue().get("token:"+jwtId);
            if ( null != tokenUser) {
                System.out.println("通过拦截器");
                return true;
            }
        }
        System.out.println("认证失败");
        response.getWriter().write("50000");
        return false;
    }



    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

    /**
     * 现在服务端给客户端签发token的功能已经差不多实现了。 那么客户端如何将token应用到以后的请求中，服务端又如何识别token呢？
     */
}
